aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNarsimhulu Musini <nmusini@cisco.com>2016-03-17 03:51:12 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2016-04-11 16:57:09 -0400
commit6e0ae74b5ca2826fa6c86a157ed5227c766156b9 (patch)
tree83fc00686403367a3d6d496609e3eadbe70774df
parentf352a0d5bafa62d1f0b044613ea42483a529f9df (diff)
snic: Handling control path queue issues
Fix handles control path queue issues such as queue full and sudden removal of hardware. Signed-off-by: Narsimhulu Musini <nmusini@cisco.com> Signed-off-by: Sesidhar Baddela <sebaddel@cisco.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/snic/vnic_dev.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/drivers/scsi/snic/vnic_dev.c b/drivers/scsi/snic/vnic_dev.c
index e0b5549bc9fb..dad5fc66effb 100644
--- a/drivers/scsi/snic/vnic_dev.c
+++ b/drivers/scsi/snic/vnic_dev.c
@@ -263,12 +263,20 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
263 int wait) 263 int wait)
264{ 264{
265 struct devcmd2_controller *dc2c = vdev->devcmd2; 265 struct devcmd2_controller *dc2c = vdev->devcmd2;
266 struct devcmd2_result *result = dc2c->result + dc2c->next_result; 266 struct devcmd2_result *result = NULL;
267 unsigned int i; 267 unsigned int i;
268 int delay; 268 int delay;
269 int err; 269 int err;
270 u32 posted; 270 u32 posted;
271 u32 fetch_idx;
271 u32 new_posted; 272 u32 new_posted;
273 u8 color;
274
275 fetch_idx = ioread32(&dc2c->wq_ctrl->fetch_index);
276 if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone */
277 /* Hardware surprise removal: return error */
278 return -ENODEV;
279 }
272 280
273 posted = ioread32(&dc2c->wq_ctrl->posted_index); 281 posted = ioread32(&dc2c->wq_ctrl->posted_index);
274 282
@@ -278,6 +286,13 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
278 } 286 }
279 287
280 new_posted = (posted + 1) % DEVCMD2_RING_SIZE; 288 new_posted = (posted + 1) % DEVCMD2_RING_SIZE;
289 if (new_posted == fetch_idx) {
290 pr_err("%s: wq is full while issuing devcmd2 command %d, fetch index: %u, posted index: %u\n",
291 pci_name(vdev->pdev), _CMD_N(cmd), fetch_idx, posted);
292
293 return -EBUSY;
294 }
295
281 dc2c->cmd_ring[posted].cmd = cmd; 296 dc2c->cmd_ring[posted].cmd = cmd;
282 dc2c->cmd_ring[posted].flags = 0; 297 dc2c->cmd_ring[posted].flags = 0;
283 298
@@ -299,14 +314,22 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
299 if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT) 314 if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
300 return 0; 315 return 0;
301 316
317 result = dc2c->result + dc2c->next_result;
318 color = dc2c->color;
319
320 /*
321 * Increment next_result, after posting the devcmd, irrespective of
322 * devcmd result, and it should be done only once.
323 */
324 dc2c->next_result++;
325 if (dc2c->next_result == dc2c->result_size) {
326 dc2c->next_result = 0;
327 dc2c->color = dc2c->color ? 0 : 1;
328 }
329
302 for (delay = 0; delay < wait; delay++) { 330 for (delay = 0; delay < wait; delay++) {
303 udelay(100); 331 udelay(100);
304 if (result->color == dc2c->color) { 332 if (result->color == color) {
305 dc2c->next_result++;
306 if (dc2c->next_result == dc2c->result_size) {
307 dc2c->next_result = 0;
308 dc2c->color = dc2c->color ? 0 : 1;
309 }
310 if (result->error) { 333 if (result->error) {
311 err = (int) result->error; 334 err = (int) result->error;
312 if (err != ERR_ECMDUNKNOWN || 335 if (err != ERR_ECMDUNKNOWN ||
@@ -317,13 +340,6 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
317 return err; 340 return err;
318 } 341 }
319 if (_CMD_DIR(cmd) & _CMD_DIR_READ) { 342 if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
320 /*
321 * Adding the rmb() prevents the compiler
322 * and/or CPU from reordering the reads which
323 * would potentially result in reading stale
324 * values.
325 */
326 rmb();
327 for (i = 0; i < VNIC_DEVCMD_NARGS; i++) 343 for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
328 vdev->args[i] = result->results[i]; 344 vdev->args[i] = result->results[i];
329 } 345 }