diff options
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 65 |
1 files changed, 29 insertions, 36 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 9a3dd20ea93a..8bbb1c81bf86 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -1305,6 +1305,34 @@ static int cciss_getnodename(ctlr_info_t *h, void __user *argp) | |||
1305 | return 0; | 1305 | return 0; |
1306 | } | 1306 | } |
1307 | 1307 | ||
1308 | static int cciss_setnodename(ctlr_info_t *h, void __user *argp) | ||
1309 | { | ||
1310 | NodeName_type NodeName; | ||
1311 | unsigned long flags; | ||
1312 | int i; | ||
1313 | |||
1314 | if (!argp) | ||
1315 | return -EINVAL; | ||
1316 | if (!capable(CAP_SYS_ADMIN)) | ||
1317 | return -EPERM; | ||
1318 | if (copy_from_user(NodeName, argp, sizeof(NodeName_type))) | ||
1319 | return -EFAULT; | ||
1320 | spin_lock_irqsave(&h->lock, flags); | ||
1321 | /* Update the field, and then ring the doorbell */ | ||
1322 | for (i = 0; i < 16; i++) | ||
1323 | writeb(NodeName[i], &h->cfgtable->ServerName[i]); | ||
1324 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); | ||
1325 | for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) { | ||
1326 | if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) | ||
1327 | break; | ||
1328 | udelay(1000); /* delay and try again */ | ||
1329 | } | ||
1330 | spin_unlock_irqrestore(&h->lock, flags); | ||
1331 | if (i >= MAX_IOCTL_CONFIG_WAIT) | ||
1332 | return -EAGAIN; | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1308 | static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | 1336 | static int cciss_ioctl(struct block_device *bdev, fmode_t mode, |
1309 | unsigned int cmd, unsigned long arg) | 1337 | unsigned int cmd, unsigned long arg) |
1310 | { | 1338 | { |
@@ -1325,42 +1353,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
1325 | case CCISS_GETNODENAME: | 1353 | case CCISS_GETNODENAME: |
1326 | return cciss_getnodename(h, argp); | 1354 | return cciss_getnodename(h, argp); |
1327 | case CCISS_SETNODENAME: | 1355 | case CCISS_SETNODENAME: |
1328 | { | 1356 | return cciss_setnodename(h, argp); |
1329 | NodeName_type NodeName; | ||
1330 | unsigned long flags; | ||
1331 | int i; | ||
1332 | |||
1333 | if (!arg) | ||
1334 | return -EINVAL; | ||
1335 | if (!capable(CAP_SYS_ADMIN)) | ||
1336 | return -EPERM; | ||
1337 | |||
1338 | if (copy_from_user | ||
1339 | (NodeName, argp, sizeof(NodeName_type))) | ||
1340 | return -EFAULT; | ||
1341 | |||
1342 | spin_lock_irqsave(&h->lock, flags); | ||
1343 | |||
1344 | /* Update the field, and then ring the doorbell */ | ||
1345 | for (i = 0; i < 16; i++) | ||
1346 | writeb(NodeName[i], | ||
1347 | &h->cfgtable->ServerName[i]); | ||
1348 | |||
1349 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); | ||
1350 | |||
1351 | for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) { | ||
1352 | if (!(readl(h->vaddr + SA5_DOORBELL) | ||
1353 | & CFGTBL_ChangeReq)) | ||
1354 | break; | ||
1355 | /* delay and try again */ | ||
1356 | udelay(1000); | ||
1357 | } | ||
1358 | spin_unlock_irqrestore(&h->lock, flags); | ||
1359 | if (i >= MAX_IOCTL_CONFIG_WAIT) | ||
1360 | return -EAGAIN; | ||
1361 | return 0; | ||
1362 | } | ||
1363 | |||
1364 | case CCISS_GETHEARTBEAT: | 1357 | case CCISS_GETHEARTBEAT: |
1365 | { | 1358 | { |
1366 | Heartbeat_type heartbeat; | 1359 | Heartbeat_type heartbeat; |